package com.dhcc.DRGsHosp.facade.impl;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import net.sf.ehcache.CacheManager;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.dhcc.DRGsHosp.application.FileUploadApplication;
import com.dhcc.DRGsHosp.application.XPathParseApplication;
import com.dhcc.DRGsHosp.facade.DrawDataFromHisFacade;
import com.dhcc.DRGsHosp.facade.FileUploadFacade;
import com.dhcc.DRGsHosp.facade.XPathParseFacade;
import com.dhcc.DRGsHosp.facade.XmlStructureFacade;
import com.dhcc.DRGsHosp.infra.util.GlobalData;
import com.dhcc.DRGsHosp.infra.util.StringUtils;

/**
 * 
 * @title		:DrawDataFromHisFacadeImpl.java
 * @description	:定时从HIS库抽取数据
 * @author		:mazhaoyan
 * @date		:2016年4月22日
 * @version     :1.0
 * @copyright   :DHCC 2013-2014
 */

public class DrawDataFromHisFacadeImpl implements DrawDataFromHisFacade{
	private static final Logger logger = LoggerFactory.getLogger(DrawDataFromHisFacadeImpl.class);
	
	@Autowired
	private XPathParseApplication xPathParseApplication;
	
	
	@Autowired
	private XPathParseFacade xPathParseFacade;
	
	@Autowired
	private XmlStructureFacade xmlStructureFacade;
	
	@Autowired
	private FileUploadApplication fileUploadApplication;
	
	@Autowired
	private FileUploadFacade fileUploadFacade;
	
	@Autowired
    private CacheManager cacheManager;
	
	/**
	 * 
	 * @methodname    :drawHisData
	 * @description   : 定时任务方法 从HIS库中抽取上一个月的已经编目的数据
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月28日
	 */
	@Override
	public void drawHisData() {
		//获取系统日期
		SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
		String date = dateFormat.format(new Date());
		System.out.println("自动任务:正在导入编目日期为"+date+"的数据……");
		drawHisDataByDay("<Request><SaveDate>"+date+"</SaveDate></Request>");
	}
	
    public void drawHisDataByDay(String day) {
    	
		//获取webServices路径
    	String dayMonitor = "";
		String wsUrl = "";//抽取编目数据地址
		String method = "";//抽取编目数据方法
		dayMonitor=GlobalData.sysConfig.get("DRAW_HIS_DATA");
		if(StringUtils.hasLength(dayMonitor)&&dayMonitor.split("θ").length==2){
			wsUrl = dayMonitor.split("θ")[0];
			method = dayMonitor.split("θ")[1];
		}
		//动态调用
		JaxWsDynamicClientFactory factory=JaxWsDynamicClientFactory.newInstance();
		Client client=factory.createClient(wsUrl);

		
    	
		String xml="";//xml字符串
		try {
			Object[] objects=client.invoke(method,day);
			xml = (String) objects[0];
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		parseAndSaveData(xml);
    }
    
    /**
	 * @methodname    :parseAndSaveData
	 * @description   : 解析并保存数据
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月29日
	 */
	@SuppressWarnings("unchecked")
	private void parseAndSaveData(String xml) {
    	try {
	    	//读取文件 转换成Document
	    	Document document = DocumentHelper.parseText(xml);
	    	//获取根节点元素对象  
			Element root = document.getRootElement();
			InputStream propInputStream = DrawDataFromHisFacadeImpl.class.getResourceAsStream("/nodeconfig.properties");
			Properties properties = new Properties();
			properties.load(propInputStream);
			String repeatNode = properties.getProperty("mr_node_address");
			if(!StringUtils.hasLength(repeatNode)){
				logger.error("REPEAT_NODE is null 请配置REPEAT_NODE");
			}
			Map<String,Object> initMap = xmlStructureFacade.getInitProperty();
			Map<String,Object> xPathMap = xPathParseApplication.getMrXPathMap("xmlFile");
			//获取重复节点
			List<Element> nodeChild = root.selectNodes(repeatNode);
			int allCnt = nodeChild.size();
			if(allCnt==0){
				logger.error("重复路径为 "+ repeatNode+ " 此路径下没有数据");
			}
			//线程仓库
			Storage storage = new Storage();
			ExecutorService parseMrDataPools = Executors.newFixedThreadPool(10);//解析获取首页数据线程池
			ExecutorService saveMrDataPools = Executors.newFixedThreadPool(10);//首保存首页数据线程池
			for(Element node: nodeChild){
				parseMrDataPools.execute(new ParseMrdataXML(node,storage,initMap,xPathMap));//解析获取首页数据
				saveMrDataPools.execute(new SaveMrData(storage,initMap));//保存首页数据
			}
			parseMrDataPools.shutdown();
			saveMrDataPools.shutdown();
			parseMrDataPools.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
			saveMrDataPools.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
			cacheManager.clearAll();
    	}
    	catch (Exception e) {
    		logger.error(e.getMessage());
		}
	}
	/**
     * 
     * @ClassName: parseMrdata  
     * @Description ：    解析获取首页数据
     * @Date: 2018年4月3日 下午3:20:17  
     * @Author mazhaoyan 
     * @Version 2.5.0 DHC-DRGs
     */
	public class ParseMrdataXML extends Thread{
		private Element node;
		private Storage storage = null;
		private Map<String,Object> initMap;
		private Map<String,Object> xPathMap;
		
		public ParseMrdataXML(Element node,Storage storage,Map<String,Object> initMap,Map<String,Object> xPathMap){
			this.node = node;
			this.storage = storage;
			this.initMap = initMap;
			this.xPathMap = xPathMap;
		}
		
		public void run() {
			Map<String, Object> caseMap = xPathParseFacade.parseXmlNode(node,initMap,xPathMap);
			try {
				storage.push(caseMap);//生产
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
	    } 
	}
	/**
	 * 
	 * @ClassName: SaveMrData  
	 * @Description ： 保存首页数据
	 * @Date: 2018年4月3日 下午3:21:34  
	 * @Author mazhaoyan 
	 * @Version 2.5.0 DHC-DRGs
	 */
	public class SaveMrData extends Thread{
		private Storage storage = null;
		private Map<String,Object> initMap;
		
		public SaveMrData(Storage storage,Map<String,Object> initMap){
			this.storage = storage;
			this.initMap = initMap;
		}
		public void run(){
			try {
				//消费
				Map<String, Object> caseMap = storage.pop();
				if(caseMap!=null){
					String errInfo = fileUploadApplication.saveCaseInfo(caseMap);//保存
					if(StringUtils.hasLength(errInfo)){
						//写入log日志
						String pMainIndex = caseMap.get("pMainIndex").toString();
						logger.error(pMainIndex+" "+errInfo);
					}else{
						fileUploadFacade.assembleAndGroup(caseMap,initMap);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();	
			}
		}
	}
}
